#pragma cone
#include <iostream>
#include <pthread.h>
#include <thread>
#include <vector>
#include <queue>
#include <unistd.h>
#include <mutex>
#include "Mutex.hpp"

const int gmax = 3;

using std::queue;
using std::thread;
using std::vector;

template <class T>
class threadpool
{
private:
    bool IsQueueEmpty()
    {
        return _task_queue.empty();
    }
    void ThreadWait()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }
    pthread_mutex_t *Mutex()
    {
        return &_mutex;
    }
       
     threadpool(const int &num = gmax) : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        for (int i = 0; i < _num; i++)
        {
            pthread_t * t = new pthread_t;
            threads.push_back(t);
        }
    }

public:
    void push(const T &in)
    {
        LockGuard lockguard(this->Mutex());
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

    static void *handler(void *args) // 类内部调用，会有this指针 参数会不同导致无法调用，
    {                                // 所以要用static变成静态函数，但是变成静态函数 也就导致无法直接访问成员
        threadpool<T> *tp = static_cast<threadpool<T> *>(args);
        while (1)
        {
            T task;
            {
                LockGuard lockguard(tp->Mutex());
                while(tp->IsQueueEmpty())
                {
                    tp->ThreadWait();
                }
                task = tp->pop();
                std::cout<<"接收一个任务"<<std::endl;
            }
            task();
        }


        return nullptr;
    }
    
    void start()
    {
        for(int i =0;i<_num;i++)
        {
            pthread_create(threads[i],nullptr,handler,(void*)this);
        }
    }

    void end()
    {
        for(auto& t:threads)
        {
            pthread_join(*t,nullptr);
        }
    }

   static threadpool* GetInstance()
    {
        if(nullptr == tp) //如果tp不为空不需要再去竞争锁
        {
            singmutex.lock(); //也有可能多线程去申请单例模式，会有线程不安全问题所以要上锁
            if(nullptr == tp) //单例模式中的懒汉模式，等我们需要用到的时候在创建 又叫(延迟加载)
            {
                tp = new threadpool();
            }
            singmutex.unlock();
        }
        return tp;
    }

    ~threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _num;                      // 线程的数量
    std::vector<pthread_t*> threads; // 线程数组
    std::queue<T> _task_queue;     // 队列
    pthread_mutex_t _mutex;        // 互斥锁
    pthread_cond_t _cond;          // 条件变量

    static threadpool<T>* tp;  //单例指针
    static std::mutex singmutex;
};
template<class T>
threadpool<T>* threadpool<T>::tp = nullptr;
template<class T>
std::mutex threadpool<T>::singmutex;